package com.archgeek.java.filechannel;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

/**
 * @author pizhihui
 * @date 2023-04-03 14:52
 */
public class MmapVsFileChannelPerformanceTest {


    private static final String FILENAME = "test.txt";
    private static final String CONTENT = "Hello, world!";
    private static final int ITERATIONS = 1000000;


    public static void main(String[] args) throws Exception {
        // 创建测试文件
        createFile(FILENAME, CONTENT);

        // 测试使用mmap进行文件读写
        System.out.println("start mmap file..........");
        long mmapStart = System.currentTimeMillis();
        for (int i = 0; i < ITERATIONS; i++) {
            testMmap(FILENAME);
        }
        long mmapEnd = System.currentTimeMillis();
        System.out.println("mmap time: " + (mmapEnd - mmapStart) + "ms");

        // 测试使用FileChannel进行文件读写
        long fileChannelStart = System.currentTimeMillis();
        for (int i = 0; i < ITERATIONS; i++) {
            testFileChannel(FILENAME);
        }
        long fileChannelEnd = System.currentTimeMillis();
        System.out.println("FileChannel time: " + (fileChannelEnd - fileChannelStart) + "ms");

        // 删除测试文件
        deleteFile(FILENAME);
    }


    private static void createFile(String filename, String content) throws IOException {
        PrintWriter writer = new PrintWriter(new FileWriter(filename));
        writer.print(content);
        writer.close();
    }

    private static void deleteFile(String filename) {
        new File(filename).delete();
    }



    private static void testMmap(String filename) throws IOException {
        FileChannel channel = new RandomAccessFile(filename, "rw").getChannel();
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());

        // 从mmap中读取数据
        byte[] bytes = new byte[buffer.limit()];
        buffer.get(bytes);
        String content = new String(bytes, Charset.forName("UTF-8"));

        // 向mmap中写入数据
        buffer.clear();
        buffer.put("mmap write".getBytes(Charset.forName("UTF-8")));
        buffer.force();

        channel.close();
    }


    private static void testFileChannel(String filename) throws IOException {
        FileChannel channel = new RandomAccessFile(filename, "rw").getChannel();
        ByteBuffer buffer = ByteBuffer.allocate((int) channel.size());

        // 从FileChannel中读取数据
        channel.read(buffer);
        buffer.flip();
        String content = Charset.forName("UTF-8").decode(buffer).toString();

        // 向FileChannel中写入数据
        buffer.clear();
        buffer.put("FileChannel write".getBytes(Charset.forName("UTF-8")));
        buffer.flip();
        channel.write(buffer);

        channel.close();
    }

}
